package com.appistry.storage.util;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.appistry.storage.File;
import com.appistry.storage.FileMetaData;
import com.appistry.storage.Worker;
import com.appistry.storage.WorkerConfiguration;
import com.appistry.storage.WorkerInfo;
import com.appistry.storage.domain.impl.FileImpl;
import com.appistry.storage.domain.impl.FileMetaDataImpl;
import com.appistry.storage.domain.impl.WorkerConfigurationImpl;
import com.appistry.storage.domain.impl.WorkerImpl;
import com.appistry.storage.domain.impl.WorkerInfoImpl;
import com.appistry.storage.rest.RestStorageManager;

public class JsonTransformUtil {
	private static final String COLON = ":";
	private static final String IP = "ip";
	private static final String AVAILABLE = "available";
	private static final String MAC = "mac";
	private static final String STATE = "state";
	private static final String OS = "os";
	private static final String TERRITORY = "territory";
	private static final String TOTAL_BYTES = "total_bytes";
	private static final String AVAILABLE_BYTES = "available_bytes";
	private static final String MOUNT_PATH = "mountPath";
	private static final String REST_PORT = "restPort";
	private static final String REST_PORT_2 = "rest_port";
	private static final String DEFAULT_R = "defaultR";
	private static final String DEFAULT_W = "defaultW";
	private static final String DEFAULT_N = "defaultN";
	private static final String INDEX_COPIES = "indexCopies";
	private static final String NETWORK_TIMEOUT = "networkTimeout";
	private static final String MEMBERSHIP_EXCHANGE_INTERVAL = "membershipExchangeInterval";
	private static final String HEALING = "healing";
	private static final String FREE_SPACE_MIN = "freeSpaceMin";
	private static final String SECURITY = "security";
	private static final String SECURITY_FILE_MONITOR_INTERVAL = "securityFileMonitorInterval";
	private static final String SSL = "ssl";
	private static final String SSL_CERTIFICATE_FILE = "sslCertificateFile";
	private static final String VERSION = "version";
	private static final String MIN_WRITE_COPIES = "min_write_copies";
	private static final String MIN_READ_COPIES = "min_read_copies";
	private static final String NUM_COPIES = "num_copies";
	private static final String DELETED = "deleted";
	private static final String CREATED_TIME = "created_time";
	private static final String MODIFIED_TIME = "modified_time";
	private static final String SIZE = "size";

	public static Map<String, FileMetaData> toWorkerFileMetaDataMap(String json)
			throws JSONException {
		HashMap<String, FileMetaData> workerFileMetaDataMap = new HashMap<String, FileMetaData>();
		JSONObject jsonObj = new JSONObject(json);

		Iterator<?> itr = jsonObj.keys();
		while (itr.hasNext()) {
			String ip = (String) itr.next();
			FileMetaDataImpl fileMetaData = new FileMetaDataImpl();

			fileMetaData.setVersion(jsonObj.getJSONObject(ip)
					.getString(VERSION));
			fileMetaData.setMinWriteCopies(jsonObj.getJSONObject(ip).getInt(
					MIN_WRITE_COPIES));
			fileMetaData.setMinReadCopies(jsonObj.getJSONObject(ip).getInt(
					MIN_READ_COPIES));
			fileMetaData.setNumCopies(jsonObj.getJSONObject(ip).getInt(
					NUM_COPIES));
			fileMetaData.setDeleted(jsonObj.getJSONObject(ip).getBoolean(
					DELETED));
			fileMetaData.setCreateTime(new Date(jsonObj.getJSONObject(ip)
					.getLong(CREATED_TIME) * 1000));
			fileMetaData.setModifiedTime(new Date(jsonObj.getJSONObject(ip)
					.getLong(MODIFIED_TIME) * 1000));
			fileMetaData.setSize(jsonObj.getJSONObject(ip).getLong(SIZE));

			workerFileMetaDataMap.put(ip, fileMetaData);
		}

		return workerFileMetaDataMap;
	}

	public static List<File> toFilesWithMetaData(RestStorageManager manager,
			String json) throws JSONException {
		List<File> files = new ArrayList<File>();

		JSONObject jsonObj = new JSONObject(json);
		Iterator<?> itr = jsonObj.keys();

		while (itr.hasNext()) {
			String filename = (String) itr.next();

			if (!jsonObj.isNull(filename)) {
				String metaDataJson = jsonObj.getString(filename);
				Map<String, FileMetaData> workerFileMetaDataMap = toWorkerFileMetaDataMap(metaDataJson);

				FileMetaData fileMetaData = workerFileMetaDataMap.values()
						.iterator().next();
				File file = new FileImpl(manager, filename, fileMetaData);
				files.add(file);
			} else {
				files.add(new FileImpl(manager, filename));
			}
		}

		return files;
	}

	public static List<File> toFiles(RestStorageManager manager, String json)
			throws JSONException {
		JSONArray jsonArray = new JSONArray(json);
		List<File> files = new ArrayList<File>();
		for (int i = 0; i < jsonArray.length(); i++) {
			// Get info
			String filename = jsonArray.getString(i);

			// Create File
			File file = new FileImpl(manager, filename);

			files.add(file);
		}
		return files;
	}

	public static WorkerConfiguration toWorkerConfiguration(String json)
			throws JSONException {
		WorkerConfigurationImpl workerConfiguration = new WorkerConfigurationImpl();
		JSONObject jsonObj = new JSONObject(json);

		workerConfiguration.setMountPath(jsonObj.getString(MOUNT_PATH));
		workerConfiguration.setPort(jsonObj.getInt(REST_PORT));
		workerConfiguration.setDefaultRead(jsonObj.getInt(DEFAULT_R));
		workerConfiguration.setDefaultWrite(jsonObj.getInt(DEFAULT_W));
		workerConfiguration.setDefaultNumCopies(jsonObj.getInt(DEFAULT_N));
		workerConfiguration.setIndexCopies(jsonObj.getInt(INDEX_COPIES));
		workerConfiguration.setNetworkTimeout(jsonObj.getInt(NETWORK_TIMEOUT));
		workerConfiguration.setMembershipExchangeInterval(jsonObj
				.getInt(MEMBERSHIP_EXCHANGE_INTERVAL));
		workerConfiguration.setHealingStatus(jsonObj.getString(HEALING));
		workerConfiguration.setFreeSpaceMin(jsonObj.getDouble(FREE_SPACE_MIN));
		workerConfiguration.setSecurityStatus(jsonObj.getString(SECURITY));
		workerConfiguration.setSecurityMonitorInterval(jsonObj
				.getInt(SECURITY_FILE_MONITOR_INTERVAL));
		workerConfiguration.setSslStatus(jsonObj.getString(SSL));
		workerConfiguration.setSslCertificateFile(jsonObj
				.getString(SSL_CERTIFICATE_FILE));

		return workerConfiguration;
	}

	public static WorkerInfo toWorkerInfo(String json) throws JSONException {
		WorkerInfoImpl workerInfo = new WorkerInfoImpl();
		JSONObject jsonObj = new JSONObject(json);
		workerInfo.setMacAddress(jsonObj.getString(MAC));
		workerInfo.setState(jsonObj.getString(STATE));
		workerInfo.setOperatingSystem(jsonObj.getString(OS));
		workerInfo.setTerritory(jsonObj.getString(TERRITORY));
		workerInfo.setTotalBytes(jsonObj.getLong(TOTAL_BYTES));
		workerInfo.setAvailableBytes(jsonObj.getLong(AVAILABLE_BYTES));

		return workerInfo;
	}

	public static List<String> toFileIps(String json) throws JSONException {
		JSONArray jsonArray = new JSONArray(json);
		List<String> ips = new ArrayList<String>();
		for (int i = 0; i < jsonArray.length(); i++) {
			String ip = jsonArray.getString(i).split(COLON)[0];
			ips.add(ip);
		}
		return ips;
	}

	public static List<String> toFileLocations(String json)
			throws JSONException {
		JSONArray jsonArray = new JSONArray(json);
		List<String> locations = new ArrayList<String>();
		for (int i = 0; i < jsonArray.length(); i++) {
			String location = jsonArray.getString(i);
			locations.add(location);
		}
		return locations;
	}

	public static List<Worker> toWorkers(RestStorageManager manager, String json)
			throws JSONException {
		JSONArray jsonArray = new JSONArray(json);
		List<Worker> workers = new ArrayList<Worker>();
		for (int i = 0; i < jsonArray.length(); i++) {
			// Get info
			JSONObject jsonObj = jsonArray.getJSONObject(i);
			String ip = jsonObj.getString(IP);
			int port = jsonObj.getInt(REST_PORT_2);
			boolean isAvailable = jsonObj.getBoolean(AVAILABLE);

			WorkerImpl worker = new WorkerImpl(manager, ip);
			worker.setAvailable(isAvailable);
			worker.setPort(port);
			workers.add(worker);
		}
		return workers;
	}

	public static List<String> toTerritories(String json) throws JSONException {
		JSONArray jsonArray = new JSONArray(json);
		List<String> territories = new ArrayList<String>();
		for (int i = 0; i < jsonArray.length(); i++) {
			// Get info
			String territory = jsonArray.getString(i);

			territories.add(territory);
		}
		return territories;
	}

	public static String toTerritory(String json) throws JSONException {
		JSONObject jsonObj = new JSONObject(json);
		return jsonObj.getString(TERRITORY);
	}

	public static List<Worker> toWorkersByTerritories(
			RestStorageManager manager, String json) throws JSONException {
		JSONArray jsonArray = new JSONArray(json);
		List<Worker> workers = new ArrayList<Worker>();
		for (int i = 0; i < jsonArray.length(); i++) {
			// Get info
			String location = jsonArray.getString(i);
			String ip = location.split(COLON)[0];
			int port = Integer.parseInt(location.split(COLON)[1]);
			boolean isAvailable = true;

			WorkerImpl worker = new WorkerImpl(manager, ip);
			worker.setAvailable(isAvailable);
			worker.setPort(port);
			workers.add(worker);
		}
		return workers;
	}
}
